
/*---------begin changed by wangwei--------------*/
//the whole file is changed, the original file is named as p_pcbcom_old.c
/*---------end changed---------------------------*/

/* $Header: p_pcbcom.c,v 2.2 01/10/02 10:27:52 przybyls Exp $ */


/***********************************************************************/
/*                                                                     */
/*                  Copyright Hewlett-Packard Co. 1991                 */
/*                                                                     */
/***********************************************************************/

/***********************************************************************/
/* MODULE NAME:                                                        */
/* ============                                                        */
/*                                                                     */
/* Author:                                                             */
/*                                                                     */
/* MODULE PURPOSE:                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/*                                                                     */
/***********************************************************************/


/*****************************/
/*   GLOBAL INCLUDE FILES    */
/*****************************/


#include <typedefs.h>
#include <m68332.h>
#include <error.h>
#include <p_wkfile.h>
#include <wkfile.h>
#include <zone_config.h>
#include <i_op.h>
#include <p_status.h>
#include <ramps.h>
#include <zone_status.h>
#include <status.h>
#include <p_filter.h>
#include <stddef.h>
#include <list_mgmt.h>
#include <pcb_defs.h>
#include <iomap.h>
#include <512.h>
#include <std_ops.h>
#include <task_pub.h>
#include <regs.h>
#include <exception.h>
#include <err_handler.h>
/* #include <p_ui.h> */
#include <keyboard.h>
#include <display.h>

/*****************************/
/*   LOCAL INCLUDE FILES     */
/*****************************/

#include "proto.h"
#include "p_err.h"
#include "p_tcomp.h"

/*****************************/
/*   GLOBAL VARIABLES        */
/*****************************/


/*****************************/
/*   EXTERNAL VARIABLES      */
/*****************************/

extern KEYCODE GetKeyFromKeyQueue ( void );

/*****************************/
/*   LOCAL DEFINES           */
/*****************************/

#define WRITE_CKSUM_WORD 15
#define  READ_CKSUM_WORD 15


/*****************************/
/*   STATIC VARIABLES        */
/*****************************/


/*****************************/
/*   IMPLEMENT SECTION       */
/*****************************/

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void ExecutePcbCommand ( pQUEUE_ENTRY buffer )

/**end_proto**/
{

    pQUEUE_HEAD queue;


    Active_Buffer_Number = ( buffer - &Pneu_Buffer_Pool[0] );
    Buffer_Number = Active_Buffer_Number;   /* set up for pneu_keys display */

    if ( (ZONES_CONFIG2 & PNEU_BD_PRESENT) != 0 )  /* if board not there .... */
    {
         buffer->PCB_Response[0] = 0xffff;
         buffer->PCB_Response[1] = 0x0000;
         buffer->PCB_Response[2] = 0x0000;
         buffer->PCB_Response[3] = 0x0000;
         buffer->PCB_Response[4] = 0x0000;
         buffer->PCB_Response[5] = 0x0000;
         buffer->PCB_Response[6] = 0x0000;
         buffer->PCB_Response[7] = 0x0000;
         buffer->PCB_Response[8] = 0x0000;
         buffer->PCB_Response[9] = 0x0000;
         buffer->PCB_Response[10] = 0x0000;
         buffer->PCB_Response[11] = 0x0000;
         buffer->PCB_Response[12] = 0x0000;
         buffer->PCB_Response[13] = 0x0000;
         buffer->PCB_Response[14] = 0x0000;
         buffer->PCB_Response[15] = 0xffff;

         return;
    }


    if ( Initialization_Complete == TRUE )
    {        /* the interrupt system is up and operational, 512 is handling the display */

          queue = GetResponseQueuePtr();
          buffer->Return_Queue = queue;

          Pcb_Cmd_Sent = FALSE;
          while ( Stepping &&( Go != TRUE ))  Task_yield();
          Go = FALSE;
pthread_mutex_lock(&queue_mut); 
          LinkBufferToTail( buffer, &Pneu_Cmd_Queue );
pthread_mutex_unlock(&queue_mut); 

          WaitForPneuResponse();

          GetBuffer( buffer, queue );
          if ( buffer == NULL )
          {
                PneuFatalError( 0, FE_NO_BUFFER );
                return;
          }

          Pcb_Cmd_Sent = TRUE;
          while ( Stepping &&( Go != TRUE ))  Task_yield();
          Go = FALSE;


    }
    else
    {  /* primitive boot in progress, we must handle keyboard and display ourselves */
          Pcb_Cmd_Sent = FALSE;
/*
          while ( Stepping && ( Go != TRUE ) )
          {
               FEED_THE_WATCHDOG;
               OutputCharToDisplay();
               WAIT_FOR_512_TO_RISE;
               OutputCharToDisplay();
               KeyboardDriver();

               if (Key_Q_Head != Key_Q_Tail)
               {
                   Pneu_Keyboard ( GetKeyFromKeyQueue() );
                   PneuFakeDisplay();
               }
          }
          Go = FALSE;

*/
          SendBufferToPCB(   buffer->PCB_Command );
          ReadBufferFromPCB( buffer->PCB_Response );
          Pcb_Cmd_Sent = TRUE;
/*
          while (Stepping && ( Go != TRUE ))
          {
               FEED_THE_WATCHDOG;
               OutputCharToDisplay();
               WAIT_FOR_512_TO_RISE;
               OutputCharToDisplay();
               KeyboardDriver();

               if (Key_Q_Head != Key_Q_Tail)
               {
                   Pneu_Keyboard ( GetKeyFromKeyQueue() );
                   PneuFakeDisplay();
               }
          }
          Go = FALSE;
*/
          Pcb_Cmd_Sent = FALSE;
    }


    /*Revisit: */
//    Go = FALSE;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

U_INT16 CheckIfPcbIsAlive(void)

/**end_proto**/
{
   pQUEUE_ENTRY buffer;
    U_INT16 i;
    U_INT16 result;
    int m;
    /* WARNING: this read must delay at least 500mS after PCB */
    /*           begins running for the self test to complete */

    //for ( i = 0 ; i < 250 ; i++ ) { WAIT_FOR_512_TO_RISE };
    //sleep(10000);
    for(m=0;m<13000000;m++){;}
    /* the pcb dsp requires an initial read before we begin the cmd-response dialog   */
    /* this verifies basic processor operation, if we do not get a good word[0] of    */
    /* the response, the dsp is really dead.  there is no checksum or retry of this   */
    /* first read, it either works or we are dead.                                    */

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
          PneuFatalError( 0, FE_NO_BUFFER );
          return FALSE;
    }

    ReadBufferFromPCB ( buffer->PCB_Response );

    if ( buffer->PCB_Response[0] != SUCCESSFUL_TURN_ON )
    {
        Inst_Status.Pneu.Poweron_Selftest_Return = buffer->PCB_Response[ 0 ];
        SetException ( DEAD_PCB );
        printf("pcb FAILED_TURN_ON,error=%d\n",buffer->PCB_Response[0]);
        return buffer->PCB_Response[ 0 ];
    }
    printf("pcb SUCCESSFUL_TURN_ON\n");
/*
    if ( Stepping )
    {
        InitPneuKeys();
        PneuFakeDisplay();
    }
*/
    SaveModuleCksums( buffer );

    LinkBufferToTail( buffer, &Pneu_Free_Pool );

    /* now ask the pcb to do a selftest and see if it is happy */
    /* be tolerant of errors, try up to three times            */

printf("begin PcbPerformSelftest\n");
    for ( i = 0; i < 3 ; i++ )
    {
        if ( PcbPerformSelftest( &result ) )
        {
            Inst_Status.Pneu.Pneu_Dsp_Alive = TRUE;
            /* it's happy, so exit the loop */
            break;
        }
        else
        {
            Inst_Status.Pneu.Pneu_Dsp_Alive = FALSE;
        }
    }

printf("end PcbPerformSelftest,the result is %d\n",Inst_Status.Pneu.Pneu_Dsp_Alive);

    if ( Inst_Status.Pneu.Pneu_Dsp_Alive == FALSE ) SetException ( DEAD_PCB );

    Inst_Status.Pneu.Poweron_Selftest_Return = result;

    return result;

 // printf("call CheckIfPcbIsAlive\n");
 // return TRUE;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void DownloadSetpoints(void)

/**end_proto**/
{

   pQUEUE_ENTRY    buffer;


  /* get a buffer to send setpts to the pcb */

   GetBuffer( buffer, &Pneu_Free_Pool );
   if ( buffer == NULL )
   {
         PneuFatalError( 0, FE_NO_BUFFER );
         return;
   }

   Active_Buffer_Number = ( buffer - &Pneu_Buffer_Pool[0] );
   Buffer_Number = Active_Buffer_Number;   /* set up for pneu_keys display */

   buffer->PCB_Command[ 0] = DOWNLOAD_SETPOINTS;

   buffer->PCB_Command[FPR_BPR_MASK_INDEX] = 0x0000; /* det & aux are alway fpr */
   buffer->PCB_Command[ FPR_BPR_MASK_INDEX ] |= ( Inst_Status.Pneu.Frnt_Inlet.PCB_Inlet_Control_Mode & 0x0003 );
   buffer->PCB_Command[ FPR_BPR_MASK_INDEX ] |= ( Inst_Status.Pneu.Back_Inlet.PCB_Inlet_Control_Mode & 0x0003 )<<2;


   buffer->PCB_Command[ FRNT_INLET_PRESSURE_INDEX ] = Inst_Status.Pneu.Frnt_Inlet.Pres_Adc_Setpt;
   buffer->PCB_Command[ FRNT_INLET_FLOW_INDEX     ] = Inst_Status.Pneu.Frnt_Inlet.Flow_Adc_Setpt;
   buffer->PCB_Command[ BACK_INLET_PRESSURE_INDEX ] = Inst_Status.Pneu.Back_Inlet.Pres_Adc_Setpt;
   buffer->PCB_Command[ BACK_INLET_FLOW_INDEX     ] = Inst_Status.Pneu.Back_Inlet.Flow_Adc_Setpt;
   buffer->PCB_Command[ FRNT_DETECTOR_GAS_1_INDEX ] = Inst_Status.Pneu.Frnt_Detector.Gas_1.Adc_Setpt;
   buffer->PCB_Command[ FRNT_DETECTOR_GAS_2_INDEX ] = Inst_Status.Pneu.Frnt_Detector.Gas_2.Adc_Setpt;
   buffer->PCB_Command[ FRNT_DETECTOR_GAS_3_INDEX ] = Inst_Status.Pneu.Frnt_Detector.Gas_3.Adc_Setpt;
   buffer->PCB_Command[ BACK_DETECTOR_GAS_1_INDEX ] = Inst_Status.Pneu.Back_Detector.Gas_1.Adc_Setpt;
   buffer->PCB_Command[ BACK_DETECTOR_GAS_2_INDEX ] = Inst_Status.Pneu.Back_Detector.Gas_2.Adc_Setpt;
   buffer->PCB_Command[ BACK_DETECTOR_GAS_3_INDEX ] = Inst_Status.Pneu.Back_Detector.Gas_3.Adc_Setpt;
   buffer->PCB_Command[ AUX_3_INDEX               ] = Inst_Status.Pneu.Aux.Aux_3.Adc_Setpt;
   buffer->PCB_Command[ AUX_4_INDEX               ] = Inst_Status.Pneu.Aux.Aux_4.Adc_Setpt;
   buffer->PCB_Command[ AUX_5_INDEX               ] = Inst_Status.Pneu.Aux.Aux_5.Adc_Setpt;


   AddChecksum ( buffer );

   buffer->Return_Queue = NULL;  /* send to forground message queue */


   /* now send the setpts */

pthread_mutex_lock(&queue_mut); 
   LinkBufferToHead(buffer, &Pneu_Cmd_Queue );
pthread_mutex_unlock(&queue_mut); 


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 DownloadPids( U_INT16 channel,
                   U_INT16 p_gain,
                   U_INT16 i_gain,
                   U_INT16 d_gain,
                   U_INT16 nl_gain )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;
    U_INT8  retry;
    BIT8   cmd_ok;



    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        buffer->PCB_Command[ 0] = DOWNLOAD_PID_TERMS;
        buffer->PCB_Command[ 1] = channel;
        buffer->PCB_Command[ 2] = i_gain;
        buffer->PCB_Command[ 3] = p_gain;
        buffer->PCB_Command[ 4] = d_gain;
        buffer->PCB_Command[ 5] = nl_gain;

        for( i=6 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );
    return cmd_ok;


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/*  DO NOT CALL FROM INTERRUPT STACK, USE FROM BACKGROUND ONLY!!!      */
/*                                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 PcbPerformSelftest( U_INT16 *result )

/**end_proto**/
{

    BIT8 cmd_ok;

    pQUEUE_ENTRY buffer;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
          PneuFatalError( 0, FE_NO_BUFFER );
          return FALSE;
    }

    buffer->PCB_Command[ 0] = PERFORM_SELF_TEST;

    AddChecksum( buffer );

    ExecutePcbCommand( buffer );

    if  ( PneuChecksumError ( buffer ) || ( buffer->PCB_Response[ 0 ] != SUCCESSFUL_TURN_ON ))
    {
        cmd_ok = FALSE;
    }
    else
    {
         cmd_ok = TRUE;
    }

    *result = buffer->PCB_Response[0];
    LinkBufferToTail(buffer, &Pneu_Free_Pool);

    return cmd_ok;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 ReadEeprom( U_INT16 module, U_INT16 address, U_INT16 *value )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;
    U_INT8  retry;
    BIT8    cmd_ok;

    if ( (ZONES_CONFIG2 & PNEU_BD_PRESENT) != 0 )  /* if board not there .... */
    {
        if (( module == FRNT_DETECTOR_MODULE_NUMBER ) || ( module == BACK_DETECTOR_MODULE_NUMBER ))
        {
            *value = 0;//CheapRead( (address<<8) | module );
            return TRUE;
        }
        else
        {
            *value = 0;
            return FALSE;
        }
    }

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        buffer->PCB_Command[0] = READ_EEPROM;
        buffer->PCB_Command[1] = module;
        buffer->PCB_Command[2] = address;

        for( i=3 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

    }

    if ( cmd_ok )  *value = buffer->PCB_Response[2];
    else           *value = 0;

    LinkBufferToTail( buffer, &Pneu_Free_Pool );
    return cmd_ok;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS: NEVER CALL FROM FOREGROUND !!!!                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 PrimitiveWriteEeprom( U_INT16 module, U_INT16 address, U_INT16 value )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;
    U_INT8  retry;
    U_INT16 data;
    BIT8    cmd_ok;
    U_INT32 waitt;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        buffer->PCB_Command[0] = WRITE_EEPROM;
        buffer->PCB_Command[1] = module;
        buffer->PCB_Command[2] = address;
        buffer->PCB_Command[3] = value;

        for( i=4 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );


    if ( cmd_ok == TRUE )
    {
         /* wait 10mSec; dsp returns a busy error to read eeprom if write not done */
     //   for ( i = 0 ; i < 5 ; i++ ) { WAIT_FOR_512_TO_RISE };

         for(waitt=0;waitt<260000;waitt++){;}

         for ( i=0; i < 5; i++ )
         {
             if ( ReadEeprom( module, address, &data ) == TRUE)
             {
                 break;
             }
         }

         if  ( data == value )
         {
              return TRUE;
         }
    }

    return FALSE;

}

/**begin_proto**/

BIT8 WriteEeprom( U_INT16 module, U_INT16 address, U_INT16 value )

/**end_proto**/
{

    U_INT16 old_value;
    BIT8    result;

    if ( address == CHECKSUM )
    {
        result = PrimitiveWriteEeprom( module, address, value );
    }
    else
    {

        if ( !ReadEeprom( module, address, &old_value ) )
        {
            return FALSE;
        }

        INTERRUPTS_OFF

        /* we could try to protect writes using module serial numbers */

        Eeprom_Pfail_Mem [ module ].Write_Step     =  WRITE_NEW_VALUE;
        Eeprom_Pfail_Mem [ module ].Old_Check_Sum  =  Inst_Status.Pneu.Module_Cksums [ module ];
        Eeprom_Pfail_Mem [ module ].Old_Data_Value =  old_value;
        Eeprom_Pfail_Mem [ module ].New_Data_Value =  value;
        Eeprom_Pfail_Mem [ module ].Write_Address  =  address;

        Inst_Status.Pneu.Module_Cksums [ module ] = Inst_Status.Pneu.Module_Cksums [ module ] - old_value + value;
        Eeprom_Pfail_Mem [ module ].New_Check_Sum  =  Inst_Status.Pneu.Module_Cksums [ module ];

        INTERRUPTS_ON


        result = PrimitiveWriteEeprom( module, address, value );


        INTERRUPTS_OFF
        Eeprom_Pfail_Mem [ module ].Write_Step     =  WRITE_NEW_CHECKSUM;
        INTERRUPTS_ON


        result &= PrimitiveWriteEeprom( module, CHECKSUM, Eeprom_Pfail_Mem [ module ].New_Check_Sum );

        INTERRUPTS_OFF
        Eeprom_Pfail_Mem [ module ].Write_Step     =  WRITE_IDLE;
        INTERRUPTS_ON

    }

    return result;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void WriteDutyCycle( U_INT16 channel, U_INT16 value )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return;
    }

    buffer->Return_Queue = 0;

    buffer->PCB_Command[0] = SET_FIXED_DUTY_CYCLE;
    buffer->PCB_Command[1] = channel;
    buffer->PCB_Command[2] = value;
    buffer->PCB_Command[3] = 1;  /* a non-zero value forces fixed duty cycle */
printf("SET_FIXED_DUTY_CYCLE channel:%d,value:%d\n",channel,value);
    for( i=4 ; i<15 ; i++)
    {
        buffer->PCB_Command[i] = 0;
    }

    AddChecksum( buffer );

    ExecutePcbCommand ( buffer );

    LinkBufferToTail( buffer, &Pneu_Free_Pool );

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void EndFixedDutyCycle( U_INT16 channel )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return;
    }

    buffer->Return_Queue = 0;

    buffer->PCB_Command[0] = SET_FIXED_DUTY_CYCLE;
    buffer->PCB_Command[1] = channel;
    buffer->PCB_Command[2] = 0;
    buffer->PCB_Command[3] = 0;  /* a zero value forces fixed duty cycle off without blowing away itegral values */
                                 /* and restores normal setpoint operation */
    for( i=4 ; i<15 ; i++)
    {
        buffer->PCB_Command[i] = 0;
    }

    AddChecksum( buffer );

pthread_mutex_lock(&queue_mut); 
    LinkBufferToTail( buffer, &Pneu_Cmd_Queue );
pthread_mutex_unlock(&queue_mut); 


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 ReadDutyCycles( void )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;
    U_INT8  retry;
    BIT8    cmd_ok;


    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        buffer->PCB_Command[0] = READ_DUTY_CYCLES;

        for( i=1 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        buffer->Return_Queue = NULL;

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );
    return cmd_ok;


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void ForegroundReadDutyCycles( void )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;


        GetBuffer( buffer, &Pneu_Free_Pool );
        if ( buffer == NULL )
        {
             PneuFatalError( 0, FE_NO_BUFFER );
             return;
        }

        buffer->PCB_Command[0] = READ_DUTY_CYCLES;

        for( i=1 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        buffer->Return_Queue = NULL;

        AddChecksum( buffer );

pthread_mutex_lock(&queue_mut); 
        LinkBufferToTail( buffer, &Pneu_Cmd_Queue );
pthread_mutex_unlock(&queue_mut); 


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS: NEVER CALL FROM FOREGROUND !!!!                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 PcbPoke( U_INT16 address, U_INT32 value )

/**end_proto**/
{
    pQUEUE_ENTRY buffer;

    U_INT8  i;
    U_INT8  retry;
    BIT8    cmd_ok;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        buffer->PCB_Command[0] = POKE;
        buffer->PCB_Command[1] = address;
        buffer->PCB_Command[3] = value & 0xff;
        buffer->PCB_Command[2] = value >> 8;

        for( i=4 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );

    return cmd_ok;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:   FOREGROUND ONLY!!  do not call from background           */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void RequestEnvironment(void)

/**end_proto**/
{

   pQUEUE_ENTRY    buffer;

  /* get a buffer to send setpts to the pcb */

   GetBuffer( buffer, &Pneu_Free_Pool );
   if ( buffer == NULL )
   {
         PneuFatalError( 0, FE_NO_BUFFER );
         return;
   }

   Active_Buffer_Number = ( buffer - &Pneu_Buffer_Pool[0] );
   Buffer_Number = Active_Buffer_Number;   /* set up for pneu_keys display */

   buffer->PCB_Command[ 0] = REQUEST_ENVIRONMENT;
   AddChecksum ( buffer );

   buffer->Return_Queue = NULL;  /* send to forground message queue */


pthread_mutex_lock(&queue_mut); 
   LinkBufferToHead(buffer, &Pneu_Cmd_Queue );
pthread_mutex_unlock(&queue_mut); 


}

/**begin_proto**/

void InitializeEnvironment(void)

/**end_proto**/
{

   U_INT8  retry;
   BIT8 cmd_ok;
   pQUEUE_ENTRY    buffer;


  /* get a buffer to send setpts to the pcb */

   GetBuffer( buffer, &Pneu_Free_Pool );
   if ( buffer == NULL )
   {
         PneuFatalError( 0, FE_NO_BUFFER );
         return;
   }

   Active_Buffer_Number = ( buffer - &Pneu_Buffer_Pool[0] );
   Buffer_Number = Active_Buffer_Number;   /* set up for pneu_keys display */

   for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
   {
        buffer->PCB_Command[ 0] = REQUEST_ENVIRONMENT;
        buffer->PCB_Command[ 1] = 0x000a;

        AddChecksum ( buffer );

        ExecutePcbCommand( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

   }

   if ( cmd_ok == TRUE )
   {
         InitEnvironmentalVars( buffer );
   }
   else
   {
         /* can't to temp comp without actual temps */

         PneuFatalError( 2, CANT_INIT_ENVIRONMENT );
   }

   LinkBufferToTail( buffer, &Pneu_Free_Pool );
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

  /*  W A R N I N G !!   SendPcbCmd limitation:                 */
  /* cmd_array and response array must be at least 16 elements! */

BIT8 SendPcbCmd( U_INT16 *cmd_array, U_INT16 *resp_array )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;
    U_INT8  retry;
    BIT8    cmd_ok;


    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        for( i=0 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = *(cmd_array+i);
        }

        buffer->Return_Queue = NULL;

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

    }

    if (  cmd_ok )
    {
        for( i=0 ; i<15 ; i++)
        {
            *(resp_array+i) = buffer->PCB_Response[i];
        }
    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );
    return cmd_ok;


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/* CALLS:                                                              */
/*                                                                     */
/* LIMITATIONS:                                                        */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 PcbPeek( U_INT16 address, U_INT32 *value )

/**end_proto**/
{

    pQUEUE_ENTRY buffer;

    U_INT8  i;
    U_INT8  retry;
    BIT8    cmd_ok;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {

        buffer->PCB_Command[0] = PEEK;
        buffer->PCB_Command[1] = address;

        for( i=2 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;
    }

    if ( cmd_ok )
    {
        *value = ((buffer->PCB_Response[2]<<8) | (buffer->PCB_Response[3] & 0xff));
    }
    else
    {
        *value = 0;
    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );
    return cmd_ok;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 RestartChannel ( U_INT16 channel_mask )

/**end_proto**/
{

    U_INT8  i;
    U_INT8  retry;
    BIT8    cmd_ok;
    pQUEUE_ENTRY buffer;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        buffer->PCB_Command[0] = RESTART_CHANNELS;
        buffer->PCB_Command[1] = channel_mask;

        /* remember all channels that have ever been restarted */
        Inst_Status.Pneu.Restarted_Channel_Mask |= channel_mask;

        for( i=2 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;
    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );

    return cmd_ok;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE: to speed up method installs.                               */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void CheckIfRetryNeeded( pQUEUE_ENTRY buffer )

/**end_proto**/
{

    if ( buffer->PCB_Command[14] == 0 ) return;  /* to many retries, giveup */

    /* if it failed try again */

    if ( !CheckResponse( buffer ) )
    {
        QuickRestartChannel( buffer->PCB_Command[1], buffer->PCB_Command[14] -1 );
    }
}


/**begin_proto**/

void QuickRestartChannel ( U_INT16 channel_mask, U_INT16 allowed_retries )

/**end_proto**/
{

    U_INT8  i;
    pQUEUE_ENTRY buffer;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return;
    }

    buffer->PCB_Command[0] = RESTART_CHANNELS;
    buffer->PCB_Command[1] = channel_mask;

    /* remember all channels that have ever been restarted */
    Inst_Status.Pneu.Restarted_Channel_Mask |= channel_mask;

    for( i=2 ; i<14 ; i++)   /* leave the last word untouched, it is used in CheckIfRetryNeeded */
    {
         buffer->PCB_Command[i] = 0;
    }

    buffer->PCB_Command[14] = allowed_retries;

    AddChecksum( buffer );

     /* return response to the foreground task */
    buffer->Return_Queue = NULL;

    Pcb_Cmd_Sent = FALSE;
/*
    while ( Stepping &&( Go != TRUE ))  Task_yield();
    Go = FALSE;
*/

pthread_mutex_lock(&queue_mut); 
    LinkBufferToTail( buffer, &Pneu_Cmd_Queue );
pthread_mutex_unlock(&queue_mut); 

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 RestartAllChannels ( void )

/**end_proto**/
{

    U_INT8  i;
    U_INT8  retry;
    BIT8    cmd_ok;
    pQUEUE_ENTRY buffer;

    GetBuffer( buffer, &Pneu_Free_Pool );
    if ( buffer == NULL )
    {
         PneuFatalError( 0, FE_NO_BUFFER );
         return FALSE;
    }

    for ( retry = 0 ; retry <= MAX_RETRY_COUNT ; retry++ )
    {
        buffer->PCB_Command[0] = RESTART_CHANNELS;
        buffer->PCB_Command[1] = ALL_CHANNEL_MASK;
        /* mask out restart bit for non-epc components */

        if ( !EpcInlet( &Inst_Status.Pneu.Frnt_Inlet ) )       buffer->PCB_Command[1] &= 0xfffc;
        if ( !EpcInlet( &Inst_Status.Pneu.Back_Inlet ) )       buffer->PCB_Command[1] &= 0xfff3;
        if ( !EpcDetector( &Inst_Status.Pneu.Frnt_Detector ) ) buffer->PCB_Command[1] &= 0xff8f;
        if ( !EpcDetector( &Inst_Status.Pneu.Back_Detector ) ) buffer->PCB_Command[1] &= 0xfc7f;
        if ( !Inst_Config.Pneu.Aux_3.Functional )              buffer->PCB_Command[1] &= 0xfbff;
        if ( !Inst_Config.Pneu.Aux_4.Functional )              buffer->PCB_Command[1] &= 0xf7ff;
        if ( !Inst_Config.Pneu.Aux_5.Functional )              buffer->PCB_Command[1] &= 0xefff;


        Inst_Status.Pneu.Restarted_Channel_Mask = buffer->PCB_Command[1];

        for( i=2 ; i<15 ; i++)
        {
            buffer->PCB_Command[i] = 0;
        }

        AddChecksum( buffer );

        ExecutePcbCommand ( buffer );

        cmd_ok = CheckResponse( buffer );
        if ( cmd_ok ) break;

    }

    LinkBufferToTail( buffer, &Pneu_Free_Pool );

    return cmd_ok;

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:   FOREGROUND ONLY!!  do not call from background           */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void RequestICapCounters(void)

/**end_proto**/
{

   pQUEUE_ENTRY    buffer;


  /* get a buffer to send setpts to the pcb */

   GetBuffer( buffer, &Pneu_Free_Pool );
   if ( buffer == NULL )
   {
         PneuFatalError( 0, FE_NO_BUFFER );
         return;
   }

   Active_Buffer_Number = ( buffer - &Pneu_Buffer_Pool[0] );
   Buffer_Number = Active_Buffer_Number;   /* set up for pneu_keys display */

   buffer->PCB_Command[ 0] = REQUEST_ICAP_CTRS;

   AddChecksum ( buffer );

   buffer->Return_Queue = NULL;  /* send to forground message queue */


pthread_mutex_lock(&queue_mut); 
   LinkBufferToHead(buffer, &Pneu_Cmd_Queue );
pthread_mutex_unlock(&queue_mut); 


}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 PneuChecksumError ( pQUEUE_ENTRY buffer )

/**end_proto**/
{

   U_INT16 read_cksum;
   U_INT8  i;

   read_cksum = 0;


   for ( i = 0 ; i < READ_CKSUM_WORD ; i++ )
   {
        read_cksum += buffer->PCB_Response[ i ];
   }

   return ( read_cksum != buffer->PCB_Response[ READ_CKSUM_WORD ] );

}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void AddChecksum ( pQUEUE_ENTRY buffer )

/**end_proto**/
{

   U_INT16 cksum;
   U_INT8  i;

   cksum = 0;


   for ( i = 0 ; i < WRITE_CKSUM_WORD ; i++ )
   {
        cksum += buffer->PCB_Command[ i ];
   }

   buffer->PCB_Command[ WRITE_CKSUM_WORD ] = cksum;


}
/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

BIT8 CheckResponse( pQUEUE_ENTRY buffer )

/**end_proto**/
{

    BIT8 cmd_ok;

    if ( PneuChecksumError( buffer ) )
    {
        printf("PneuChecksumError!!\n");
/*
        SoftError( PNEU_READ_CKSUM );
        if ( Inst_Status.Pneu.Halt_On_Cksum_Error ) PneuFatalError( 2, PCB_READ_FAILURE );
        else                                        PneuFatalError( 0, PCB_READ_FAILURE );
        cmd_ok = FALSE;
*/
    }
    else
    {
        switch ( buffer->PCB_Response[0] )
        {
          case  SUCCESSFUL_TRANSFER:       cmd_ok = TRUE;
                                           break;

          case  OUTPUT_BUFFER_OVERWRITE:   //SoftError( PNEU_ERROR );
                                           Inst_Status.Pneu.Last_Pcb_Error = buffer->PCB_Response[0];
                                           cmd_ok = FALSE;
                                           break;

          case  COMMAND_CHECKSUM_ERROR:    //SoftError( PNEU_WRITE_CKSUM );
                                           Inst_Status.Pneu.Last_Pcb_Error = buffer->PCB_Response[0];
                                           cmd_ok = FALSE;
                                           break;

          case  EEPROM_BUSY:
          case  COMMAND_NOT_UNDERSTOOD:    if ( Inst_Status.Pneu.Halt_On_Error )
                                                 PneuFatalError ( 3, buffer->PCB_Response[0] );
                                           else
                                                 PneuFatalError ( 1, buffer->PCB_Response[0] );
                                           Inst_Status.Pneu.Last_Pcb_Error = buffer->PCB_Response[0];
                                           cmd_ok = FALSE;
                                           break;


          default:
          case  FATAL_ADC_INVALID:
          case  FATAL_PROGRAM_CHECKSUM:
          case  FATAL_MEMORY_ERROR:
          case  FATAL_PWM_DRIVE_ERROR:
          case  FATAL_REGISTER_TEST:
          case  FATAL_SAFETY_SHUTDOWN:
          case  FATAL_TIMESLOT_OVERRUN:    //SetException( DEAD_PCB );
                                           PneuFatalError ( 3, buffer->PCB_Response[0] );
                                           Inst_Status.Pneu.Last_Pcb_Error = buffer->PCB_Response[0];
                                           cmd_ok = FALSE;
                                           break;
        }
    }

    if ( ! cmd_ok ) Check_For_Dead_Pcb = TRUE;

    return cmd_ok;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void ActualEqualsSetpt( pQUEUE_ENTRY buffer )

/**end_proto**/
{

  U_INT8 i;
  static U_INT16 prev_values[16];

  INTERRUPTS_OFF;

   if ( buffer->PCB_Command[ 0 ] == DOWNLOAD_SETPOINTS )
   {

       if (Actual_Equals_Setpt)
       {

         buffer->PCB_Response[SHUTDOWN_MASK_INDEX]       = PFEW;

         for ( i = FRNT_INLET_PRESSURE_INDEX ; i <= AUX_5_INDEX ; i++ )
         {
             buffer->PCB_Response[ i ] = prev_values[i];
             prev_values[i] = buffer->PCB_Command[ i ];
         }
         /* PFEW = 0; reset to avoid repetative failures */
       }

   }
   else if ( buffer->PCB_Command[ 0 ] == READ_DUTY_CYCLES )
   {
       if (Actual_Equals_Setpt)
       {
         buffer->PCB_Response[SHUTDOWN_MASK_INDEX]       = 0;
         buffer->PCB_Response[FRNT_INLET_PRESSURE_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  0 ];
         buffer->PCB_Response[FRNT_INLET_FLOW_INDEX]     = Inst_Status.Pneu.Duty_Cycle_Setpts[  1 ];
         buffer->PCB_Response[BACK_INLET_PRESSURE_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  2 ];
         buffer->PCB_Response[BACK_INLET_FLOW_INDEX]     = Inst_Status.Pneu.Duty_Cycle_Setpts[  3 ];
         buffer->PCB_Response[FRNT_DETECTOR_GAS_1_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  4 ];
         buffer->PCB_Response[FRNT_DETECTOR_GAS_2_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  5 ];
         buffer->PCB_Response[FRNT_DETECTOR_GAS_3_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  6 ];
         buffer->PCB_Response[BACK_DETECTOR_GAS_1_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  7 ];
         buffer->PCB_Response[BACK_DETECTOR_GAS_2_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  8 ];
         buffer->PCB_Response[BACK_DETECTOR_GAS_3_INDEX] = Inst_Status.Pneu.Duty_Cycle_Setpts[  9 ];
         buffer->PCB_Response[AUX_3_INDEX]               = Inst_Status.Pneu.Duty_Cycle_Setpts[ 10 ];
         buffer->PCB_Response[AUX_4_INDEX]               = Inst_Status.Pneu.Duty_Cycle_Setpts[ 11 ];
         buffer->PCB_Response[AUX_5_INDEX]               = Inst_Status.Pneu.Duty_Cycle_Setpts[ 12 ];
       }
   }
   else if ( buffer->PCB_Command[ 0 ] == REQUEST_ICAP_CTRS )
   {
       if (Actual_Equals_Setpt)
       {
         buffer->PCB_Response[SHUTDOWN_MASK_INDEX]       = 0;
         buffer->PCB_Response[FRNT_INLET_PRESSURE_INDEX] = 0;
         buffer->PCB_Response[FRNT_INLET_FLOW_INDEX]     = 0;
         buffer->PCB_Response[BACK_INLET_PRESSURE_INDEX] = 0;
         buffer->PCB_Response[BACK_INLET_FLOW_INDEX]     = 0;
         buffer->PCB_Response[FRNT_DETECTOR_GAS_1_INDEX] = 0;
         buffer->PCB_Response[FRNT_DETECTOR_GAS_2_INDEX] = 0;
         buffer->PCB_Response[FRNT_DETECTOR_GAS_3_INDEX] = 0;
         buffer->PCB_Response[BACK_DETECTOR_GAS_1_INDEX] = 0;
         buffer->PCB_Response[BACK_DETECTOR_GAS_2_INDEX] = 0;
         buffer->PCB_Response[BACK_DETECTOR_GAS_3_INDEX] = 0;
         buffer->PCB_Response[AUX_3_INDEX]               = 0;
         buffer->PCB_Response[AUX_4_INDEX]               = 0;
         buffer->PCB_Response[AUX_5_INDEX]               = 0;
       }
   }
   else
   {
       if (Actual_Equals_Setpt)
       {
         buffer->PCB_Response[SHUTDOWN_MASK_INDEX]       = 0;
       }
   }

   buffer->PCB_Response[15] = 0;

   for ( i = 0 ; i < 15 ; i ++ ) buffer->PCB_Response[15] += buffer->PCB_Response[i];


   if (Actual_Equals_Setpt) buffer->PCB_Response[ 0] = SUCCESSFUL_TRANSFER;

   INTERRUPTS_ON;
}

/***********************************************************************/
/* FUNCTION:                                                           */
/* ========                                                            */
/*                                                                     */
/* PURPOSE:                                                            */
/*                                                                     */
/* RETURNED VALUE:                                                     */
/*                                                                     */
/* GLOBALS USED:                                                       */
/*                                                                     */
/***********************************************************************/
/**begin_proto**/

void UpdateEnvironmentals( pQUEUE_ENTRY buffer )

/**end_proto**/
{
  U_INT16 value;
  U_INT16 volt;


  OffsetFilter( &Inst_Status.Pneu.Environment.Ten_Volt_Filter,   buffer->PCB_Response[ 8 ] );
  Inst_Status.Pneu.Environment.Ten_Volts = GetFilteredOffset( &Inst_Status.Pneu.Environment.Ten_Volt_Filter );
  Inst_Status.Pneu.Environment.Ten_Volt_Offset = GetFilteredOffset( &Inst_Status.Pneu.Environment.Ten_Volt_Filter )
    - PCB_ADC_TEN_VOLT_STD;

  OffsetFilter( &Inst_Status.Pneu.Environment.ADC_Offset_Filter, buffer->PCB_Response[ 9 ] );
  Inst_Status.Pneu.Environment.ADC_Offset_Volts = GetFilteredOffset( &Inst_Status.Pneu.Environment.ADC_Offset_Filter );
  Inst_Status.Pneu.Environment.ADC_Offset = GetFilteredOffset( &Inst_Status.Pneu.Environment.ADC_Offset_Filter )
    - PCB_ADC_OFFSET_STD;


  Inst_Status.Pneu.Environment.Adc_Gain =
    ( Inst_Status.Pneu.Environment.Ten_Volt_Offset - Inst_Status.Pneu.Environment.ADC_Offset )
    * OFFSET_GAIN_SCALE
    / ( PCB_ADC_TEN_VOLT_STD - PCB_ADC_OFFSET_STD );

  Inst_Status.Pneu.Environment.True_Adc_Offset =
    Inst_Status.Pneu.Environment.ADC_Offset
    -  Inst_Status.Pneu.Environment.Adc_Gain * PCB_ADC_OFFSET_STD / OFFSET_GAIN_SCALE;


  /* FIT front inlet temp */

#define FIT_FILTER Inst_Status.Pneu.Frnt_Inlet.Tcomp_Tables->Thermistor.Temp_Filter
  volt = SubtractAdcOffset( buffer->PCB_Response[ 2 ] );
  Inst_Status.Pneu.Environment.Frnt_Inlet_Temp = volt;
  value = tableU ( (U_INT16 *)Inst_Status.Pneu.Frnt_Inlet.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );
  LongTimeFilterValue(FIT_FILTER, value );
  Inst_Status.Pneu.Frnt_Inlet.Tcomp_Tables->Thermistor.Module_Temperature = GetLongTimeFilteredValue(FIT_FILTER);


  /* BIT back inlet temp */

#define BIT_FILTER Inst_Status.Pneu.Back_Inlet.Tcomp_Tables->Thermistor.Temp_Filter
  volt = SubtractAdcOffset( buffer->PCB_Response[ 3 ]  );
  Inst_Status.Pneu.Environment.Back_Inlet_Temp = volt;
  value = tableU ( (U_INT16 *)Inst_Status.Pneu.Back_Inlet.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );
  LongTimeFilterValue(BIT_FILTER, value );
  Inst_Status.Pneu.Back_Inlet.Tcomp_Tables->Thermistor.Module_Temperature = GetLongTimeFilteredValue(BIT_FILTER);


#define FDT_FILTER Inst_Status.Pneu.Frnt_Detector.Tcomp_Tables->Thermistor.Temp_Filter
  volt = SubtractAdcOffset( buffer->PCB_Response[ 4 ]  );
  Inst_Status.Pneu.Environment.Frnt_Det_Temp = volt;
  value = tableU ( (U_INT16 *)Inst_Status.Pneu.Frnt_Detector.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );
  LongTimeFilterValue(FDT_FILTER, value );
  Inst_Status.Pneu.Frnt_Detector.Tcomp_Tables->Thermistor.Module_Temperature = GetLongTimeFilteredValue(FDT_FILTER);


#define BDT_FILTER Inst_Status.Pneu.Back_Detector.Tcomp_Tables->Thermistor.Temp_Filter
  volt = SubtractAdcOffset( buffer->PCB_Response[ 5 ]  );
  Inst_Status.Pneu.Environment.Back_Det_Temp = volt;
  value = tableU ( (U_INT16 *)Inst_Status.Pneu.Back_Detector.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );
  LongTimeFilterValue(BDT_FILTER, value );
  Inst_Status.Pneu.Back_Detector.Tcomp_Tables->Thermistor.Module_Temperature = GetLongTimeFilteredValue(BDT_FILTER);



#define AXT_FILTER Inst_Status.Pneu.Aux.Tcomp_Tables->Thermistor.Temp_Filter
  volt = SubtractAdcOffset( buffer->PCB_Response[ 6 ]  );
  Inst_Status.Pneu.Environment.Aux_Temp = volt;
  value = tableU ( (U_INT16 *)Inst_Status.Pneu.Aux.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );
  LongTimeFilterValue(AXT_FILTER, value );
  Inst_Status.Pneu.Aux.Tcomp_Tables->Thermistor.Module_Temperature = GetLongTimeFilteredValue(AXT_FILTER);
//printf("Aux_Temp :%d   value:%d  Filter:%d Module_Temperature:%d Offset=%x\n",volt,value,AXT_FILTER,Inst_Status.Pneu.Aux.Tcomp_Tables->Thermistor.Module_Temperature,Inst_Status.Pneu.Environment.ADC_Offset);

#define ATP_FILTER Inst_Status.Pneu.Environment.Atm_Pres_Filter
  volt = SubtractAdcOffset( buffer->PCB_Response[ 7 ]  );
  Inst_Status.Pneu.Environment.Atm_Pres = volt;
  value = VoltsToAtmPres( volt );
  LongTimeFilterValue(ATP_FILTER, value );

  Atmospheric_Pressure.Dcm2_80  = GetLongTimeFilteredValue(ATP_FILTER);
  Atmospheric_Pressure.Dcm2_160 = Atmospheric_Pressure.Dcm2_80 / 2;
  Atmospheric_Pressure.Dcm2_320 = Atmospheric_Pressure.Dcm2_80 / 4;


  Inst_Status.Pneu.Environment.Frnt_Inlet_Gas  = SubtractAdcOffset( buffer->PCB_Response[ 10 ] );
  Inst_Status.Pneu.Environment.Back_Inlet_Gas  = SubtractAdcOffset( buffer->PCB_Response[ 11 ] );
  Inst_Status.Pneu.Environment.Pneu_24_Volts   = SubtractAdcOffset( buffer->PCB_Response[ 12 ] );
}


/**begin_proto**/

void InitEnvironmentalVars( pQUEUE_ENTRY buffer )

/**end_proto**/
{
       U_INT16 value;
       U_INT16 volt;


       JamOffsetFilter( &Inst_Status.Pneu.Environment.Ten_Volt_Filter  , buffer->PCB_Response[ 8 ]);
       JamOffsetFilter( &Inst_Status.Pneu.Environment.ADC_Offset_Filter, buffer->PCB_Response[ 9 ]);



       volt = SubtractAdcOffset( buffer->PCB_Response[ 2 ] );
       value = tableU ( (U_INT16 *)Inst_Status.Pneu.Frnt_Inlet.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );

       LongTimeJamFilter(Inst_Status.Pneu.Frnt_Inlet.Tcomp_Tables->Thermistor.Temp_Filter,value);
       Inst_Status.Pneu.Frnt_Inlet.Tcomp_Tables->Thermistor.Module_Temperature = value;



       volt = SubtractAdcOffset( buffer->PCB_Response[ 3 ] );
       value = tableU ( (U_INT16 *)Inst_Status.Pneu.Back_Inlet.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );

       LongTimeJamFilter(Inst_Status.Pneu.Back_Inlet.Tcomp_Tables->Thermistor.Temp_Filter,value);
       Inst_Status.Pneu.Back_Inlet.Tcomp_Tables->Thermistor.Module_Temperature = value;




       volt = SubtractAdcOffset( buffer->PCB_Response[ 4 ] );
       value = tableU ( (U_INT16 *)Inst_Status.Pneu.Frnt_Detector.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );

       LongTimeJamFilter(Inst_Status.Pneu.Frnt_Detector.Tcomp_Tables->Thermistor.Temp_Filter,value);
       Inst_Status.Pneu.Frnt_Detector.Tcomp_Tables->Thermistor.Module_Temperature = value;



       volt = SubtractAdcOffset( buffer->PCB_Response[ 5 ] );
       value = tableU ( (U_INT16 *)Inst_Status.Pneu.Back_Detector.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );

       LongTimeJamFilter(Inst_Status.Pneu.Back_Detector.Tcomp_Tables->Thermistor.Temp_Filter,value);
       Inst_Status.Pneu.Back_Detector.Tcomp_Tables->Thermistor.Module_Temperature = value;



       volt = SubtractAdcOffset( buffer->PCB_Response[ 6 ] );
       value = tableU ( (U_INT16 *)Inst_Status.Pneu.Aux.Tcomp_Tables->Thermistor.Volts_To_Temp, volt );

       LongTimeJamFilter(Inst_Status.Pneu.Aux.Tcomp_Tables->Thermistor.Temp_Filter,value);
       Inst_Status.Pneu.Aux.Tcomp_Tables->Thermistor.Module_Temperature = value;


       volt = SubtractAdcOffset( buffer->PCB_Response[ 7 ]  );
       value = VoltsToAtmPres( volt );

       LongTimeJamFilter(Inst_Status.Pneu.Environment.Atm_Pres_Filter, value );
       Atmospheric_Pressure.Dcm2_80 = GetLongTimeFilteredValue( Inst_Status.Pneu.Environment.Atm_Pres_Filter );
       Atmospheric_Pressure.Dcm2_160 = Atmospheric_Pressure.Dcm2_80 / 2;
       Atmospheric_Pressure.Dcm2_320 = Atmospheric_Pressure.Dcm2_80 / 4;

       Inst_Status.Pneu.Environment.Frnt_Inlet_Gas  = SubtractAdcOffset( buffer->PCB_Response[ 10 ] );
       Inst_Status.Pneu.Environment.Back_Inlet_Gas  = SubtractAdcOffset( buffer->PCB_Response[ 11 ] );
       Inst_Status.Pneu.Environment.Pneu_24_Volts   = SubtractAdcOffset( buffer->PCB_Response[ 12 ] );
}

/**begin_proto**/

void SaveModuleCksums( pQUEUE_ENTRY buffer )

/**end_proto**/
{

   U_INT8 module;

   for ( module = 0 ; module < 5 ; module++ )
   {
      Inst_Status.Pneu.Module_Cksums [ module ] = buffer->PCB_Response [ module + FIRST_CHANNEL_INDEX ];
      CompleteModuleWrite( module, &Inst_Status.Pneu.Module_Cksums [ module ] );
   }
}

/**begin_proto**/

void CompleteModuleWrite( U_INT8 module, U_INT16 *calc_cksum )

/**end_proto**/
{
    U_INT16 address;
    U_INT16 value;
    U_INT16 check_sum;
    U_INT16 old_value;

    value   = Eeprom_Pfail_Mem [ module ].New_Data_Value;
    address = Eeprom_Pfail_Mem [ module ].Write_Address;
    check_sum = Eeprom_Pfail_Mem [ module ].New_Check_Sum;

    switch (  Eeprom_Pfail_Mem [ module ].Write_Step )
    {

        case WRITE_NEW_VALUE:  (void)ReadEeprom( module, address, &old_value );
                               if ( old_value != value )
                               {
                                   /* the write did not work so adjust the real chksum */
                                   *calc_cksum = *calc_cksum - old_value + value;
                               }
                               (void)PrimitiveWriteEeprom( module, address, value );
                               INTERRUPTS_OFF
                               Eeprom_Pfail_Mem [ module ].Write_Step     =  WRITE_NEW_CHECKSUM;
                               INTERRUPTS_ON

                               /* intentional fall through */

        case WRITE_NEW_CHECKSUM: (void)PrimitiveWriteEeprom( module, CHECKSUM, check_sum );
                               INTERRUPTS_OFF
                               Eeprom_Pfail_Mem [ module ].Write_Step     =  WRITE_IDLE;
                               INTERRUPTS_ON

                               /* intentional fall through */

        case WRITE_IDLE:       break;

    }
}

/**begin_proto**/

U_INT16 CalcModuleChecksum( U_INT8 module )

/**end_proto**/
{

    /* this is only invoked as a diagnostic through pneu_keys.c    */
    /* normal operation has the pcb2 calculating checksums at boot */


    U_INT16 check_sum;
    U_INT16 data_value;
    U_INT16 address;

    check_sum = 0;

    for ( address = 0 ; address <= 255 ; address ++ )
    {
        if ( address == CHECKSUM ) continue;

        (void)ReadEeprom( module, address, &data_value );

        EEPROM_Write_Address = address;  /* for display of recalculate checksum */
        EEPROM_Write_Data = data_value;  /* for display of recalculate checksum */

        check_sum += data_value;
    }

    return check_sum;

}
